<!--人员选择框组件-->
<template>
  <el-dialog v-model="stateDialog" title="人员选择" width="70%" center class="personnelSelection-dialog" @close="closeDialog">
    <div class="dialog-search">
      <el-input v-model="search" placeholder="请输入搜索内容" clearable size="large">
        <template #append>
          <el-button @click="searchBtn" type="primary">搜索</el-button>
        </template>
      </el-input>
    </div>
    <div class="dialog-menu">
      <div></div>
      <div><el-button @click="checkAll">全选</el-button></div>
      <div><el-button @click="clear">清空</el-button></div>
    </div>
    <div class="dialog-body">
      <!--树形结构页面-->
      <div class="body-left body-box">
        <el-tree lazy :props="props" :load="loadNode" node-key="dn" @node-click="nodeClick" ref="treeRef" />
      </div>
      <!--人员列表页面-->
      <div class="body-center body-box" v-loading="loading" element-loading-text="加载中...">
        <div class="center-item" v-for="(item, index) in personnelList" :key="item.userCode" @click="selectPerson(item, index)">
          <span>{{ item.userName }}</span>
          <span>/</span>
          <span class="item-departmentalLevel" :title="formatDepartmentDn(item)">{{ formatDepartmentDn(item) }}</span>
        </div>
      </div>
      <!--人员选择页面-->
      <div class="body-right body-box">
        <div
          class="right-item"
          v-for="(item, index) in personnelSelection"
          :key="item.userCode"
          @click="deletePeople(item, index)"
        >
          <span>{{ item.userName }}</span>
          <span>/</span>
          <span class="item-departmentalLevel" :title="formatDepartmentDn(item)">{{ formatDepartmentDn(item) }}</span>
        </div>
      </div>
    </div>
    <template #footer>
      <el-button @click="stateDialog = false">关闭</el-button>
      <el-button type="primary" @click="submitBtn">确认</el-button>
    </template>
  </el-dialog>
</template>

<script setup>
import { last } from "lodash-es";
import { LEVEL, CHINESE_PREFIX } from "@/utils/constConfig.js";
import { getDeptList, getPersonnelInformation } from "@/api/navigationLecture";
import useUserStore from "@/store/modules/user";
import { ElMessage } from "element-plus";
import { ref } from "vue";

const {
  user: { companyName },
} = useUserStore();
const { proxy } = getCurrentInstance();

const propData = defineProps({
  // 最大选择人数
  maxCount: {
    type: Number,
    default: 10,
  }, // 人员选择回显数据
  personnelEcho: {
    type: Array,
    default: [],
  },
});

const props = {
  id: "dn", //唯一id
  label: "name", //节点名称
  children: "children", //节点子集
  isLeaf: "leaf", //是否是子节点
}; //树形结构

//人员待选数据
const personnelList = ref([]);
//人员已选数据
const personnelSelection = ref([]);
//搜索框
const search = ref("");
//弹窗状态
const stateDialog = ref(false);
//加载状态
const loading = ref(false);
//树形结构
const treeRef = ref(null);

/**
 * 加载节点
 * @param node 节点
 * @param resolve 添加子节点
 */
const loadNode = async (node, resolve) => {
  const {
    level,
    data: { dn },
  } = node; //解构出层级和当前节点唯一dn

  try {
    const { data } = await getDeptList({ level: level + LEVEL, parentDn: dn }); //新增一个层级，所以层级level+1,获取子节点数据
    const nodeData = data.map((item) => ({ ...item, leaf: !item.leaf }));
    if (level === 0) {
      // 公司列表信息需要根据当前人的公司名称进行筛选
      return resolve(nodeData.filter((item) => item.name === companyName));
    }
    return resolve(nodeData);
  } catch (error) {
    //TODO 框架已经做统一处理。
  }
};

/**
 * 点击节点时，请求人员信息
 * @param fullName 部门名称
 */
const nodeClick = ({ fullName }) => {
  //当节点是子节点的时候，请求人员列表信息
  getPersonnel({ parentDeptFullName: fullName });
};

/**
 * 请求人员信息
 * @param params 人员请求参数
 */
const getPersonnel = async (params) => {
  try {
    loading.value = true;
    const { data } = await getPersonnelInformation(params);
    // 获取已选列表人员的userId的集合
    const userIdsToRemove = new Set(personnelSelection.value.map((item) => item.userCode));
    // 过滤掉已选列表中有存在于未选列表的人员
    personnelList.value = data.filter((item) => !userIdsToRemove.has(item.userCode));
  } catch (error) {
    //TODO 框架已经做统一处理。
  } finally {
    loading.value = false;
  }
};

/**
 * 搜索按钮点击事件
 */
const searchBtn = async () => {
  const params = {
    queryText: search.value,
    maxCount: 20,
  };
  getPersonnel(params);
};

/**
 * 人员待选框按钮点击事件
 * @param value 选择的人
 * @param index 选择的人索引
 */
const selectPerson = (value, index) => {
  //  当前已选人数小于最大选择人数
  if (personnelSelection.value.length < propData.maxCount) {
    //删除人员列表的人员
    personnelList.value = personnelList.value.filter((_, i) => i !== index);
    //添加人员列表的人员到人员选择
    personnelSelection.value.push(value);
  } else {
    ElMessage.error(`该栏目最多可选择${propData.maxCount}个值`);
  }
};

/**
 * 人员已选框按钮点击事件
 * @param value 选择的人
 * @param index 选择的人索引
 */
const deletePeople = (value, index) => {
  //删除人员列表的人员
  personnelSelection.value = personnelSelection.value.filter((_, i) => i !== index);
  //添加人员列表的人员到人员选择
  personnelList.value.push(value);
};

/**
 * 人员待选框全选事件
 */
const checkAll = () => {
  //添加人员列表的人员到人员选择
  personnelSelection.value.push(...personnelList.value);
  //删除人员列表的人员
  personnelList.value = [];
};

/**
 * 人员已选框清空事件
 */
const clear = () => {
  //添加人员选择的人员到人员列表
  personnelList.value.push(...personnelSelection.value);
  //删除人员选择的人员
  personnelSelection.value = [];
};

/**
 * 打开弹窗
 */
const showDialog = () => {
  stateDialog.value = true;
  proxy.$nextTick(() => {
    personnelSelection.value = propData.personnelEcho.map((item) => {
      const { orgShortName, ygId, label } = item;
      return {
        ...item,
        departmentDn: orgShortName,
        userCode: ygId,
        userName: label,
      };
    });
  });
};

const emit = defineEmits(["submit"]);

/**
 * 人员选择提交
 */
const submitBtn = () => {
  const data = personnelSelection.value.map((item) => {
    const { userId, userCode, userName } = item;
    return {
      ...item,
      orgUUID: userId,
      ygId: userCode,
      label: userName,
    };
  });
  emit("submit", data);
  stateDialog.value = false;
};

/**
 * 关闭弹窗重置数据
 */
const closeDialog = () => {
  personnelList.value = []; //人员待选数据
  personnelSelection.value = []; //人员已选数据
  search.value = ""; //搜索框
  const { root } = treeRef.value.store;
  root.loaded = false;
  root.expand();
};

/**
 * 格式化部门名称
 * @param dn 部门名称
 */
const formatDepartmentDn = ({ companyName, departmentDn }) => {
  if (!companyName || !departmentDn) {
    return departmentDn ?? companyName;
  }
  const data = departmentDn
    .split(",") // 将部门名称按逗号进行分割
    .filter((part) => part.startsWith("OU=")) // 筛选以 "OU=" 开头的部分
    .map((ouPart) => last(ouPart.split("="))) // 提取 "OU=" 后面的值
    .filter((value) => CHINESE_PREFIX.test(value)); // 匹配中文字符
  return data.concat(companyName).reverse().join("-");
};

defineExpose({
  showDialog,
});
</script>
<style scoped lang="less">
.personnelSelection-dialog {
  //菜单页面
  .dialog-search {
    width: 300px;
    margin-bottom: 10px;

    :deep(.el-input) {
      .el-input-group__append {
        color: #fff;
        background-color: #409eff;
        cursor: pointer;
      }
    }
  }

  //全选和清空按钮
  .dialog-menu {
    width: 100%;
    margin-bottom: 10px;
    .flex-display(@columnGap: end);

    div {
      flex: 1;
      .flex-display(@justifyContent: end);
    }
  }

  //人员选择区域
  .dialog-body {
    width: 100%;
    height: 500px;
    .flex-display(@columnGap: 20px);

    .body-box {
      flex: 1;
      border: 1px solid #c3c3c3;

      .el-tree {
        height: 100%;
        overflow-y: auto;

        &::-webkit-scrollbar {
          width: 6px;
        }

        &::-webkit-scrollbar-button {
          display: none;
        }

        &::-webkit-scrollbar-thumb {
          background-color: #dddee0;
          border-radius: 2px;
        }
      }
    }

    .body-center,
    .body-right {
      height: 100%;
      overflow-y: auto;

      &::-webkit-scrollbar {
        width: 6px;
      }

      &::-webkit-scrollbar-button {
        display: none;
      }

      &::-webkit-scrollbar-thumb {
        background-color: #dddee0;
        border-radius: 2px;
      }

      .center-item,
      .right-item {
        .flex-display(@alignItems: center; @columnGap: 10px);
        height: 30px;
        padding: 10px;
        cursor: pointer;
        font-size: 15px;

        .item-departmentalLevel {
          flex: 1;
          .text-ellipsis();
        }

        &:hover {
          background-color: #eee;
        }
      }
    }
  }
}
</style>
